home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d20 / msgq160s.arc / BUFMSG.C < prev    next >
Text File  |  1991-10-26  |  9KB  |  416 lines

  1. /*
  2.  * BUFMSG.C - Message Buffering
  3.  *
  4.  * Msged/Q message editor for QuickBBS  Copyright 1990 by P.J. Muller
  5.  *
  6.  */
  7.  
  8. /*#define TIMING*/            /* for optimization info */
  9.  
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #ifdef TIMING
  14. #include <time.h>
  15. #include <stdio.h>
  16. #endif
  17.  
  18. #include "msged.h"
  19.  
  20. #ifdef TIMING
  21. static void watch(int chk)
  22. {
  23.   static clock_t start;
  24.  
  25.   if (chk != 0) {
  26.     clock_t dif = clock()-start;
  27.     fprintf(stderr,"%-3d %ld\n", chk, dif);
  28.   } /* else */
  29.   if (chk == -1)
  30.     do {} while (getchar() != '\n');
  31.  
  32.   start = clock();
  33. } /* watch */
  34. #else
  35. #  define watch(dummy)
  36. #endif
  37.  
  38. void    clearbuffer(BUFFER *buf)
  39. {
  40.     LINE *curline;
  41.  
  42.     if      ((curline = buf->first) != NULL) {
  43.  
  44.         while   (curline->next != NULL) {
  45.             curline = curline->next;
  46.                         ptrfree(curline->prev->text);
  47.                         curline->prev->next = NULL;
  48.                         ptrfree(curline->prev);
  49.                         curline->prev = NULL;
  50.         }
  51.  
  52.         if (curline->text)
  53.             ptrfree(curline->text);
  54.  
  55.                 curline->text = NULL;
  56.         ptrfree(curline);
  57.         curline = NULL;
  58.         buf->first = NULL;
  59.         buf->last = NULL;
  60.     }
  61. }
  62.  
  63. #if ZAPTHISOUT        /* OLD NEW VERSION */
  64. static void normalize(char *s);
  65.  
  66. BUFFER buffer(char **ss)
  67. {
  68.         char   *tmp, *t, *t1, *s;
  69.     LINE   *p;
  70.     BUFFER buf;
  71.     int     i;
  72.     int     column;
  73.  
  74.     /* init the buffer variables */
  75.  
  76.     buf.first = buf.last = NULL;
  77.  
  78.     clearbuffer();        /* clear global buffer (bad code) */
  79.     watch(0);
  80.     normalize(*ss);        /* remove soft \r, convert \r\n to \n */
  81.     watch(2);
  82.         if ((*ss = (char *) realloc(*ss, strlen(*ss) + 1)) == NULL)
  83.         return buf;
  84.  
  85.         s = *ss;
  86.  
  87.     /* wrap the text into the buffer */
  88.  
  89.         if ((t = (char *) calloc(1, (rm + rm/2))) == NULL)
  90.         return buf;
  91.  
  92.         if ((tmp = (char *) calloc(1, (rm + rm/2))) == NULL) {
  93.                 ptrfree(t);
  94.         return buf;
  95.         }
  96.  
  97.     i = 0;
  98.  
  99.     buf.first = NULL;
  100.     column = 0;
  101.  
  102.     while (*s != EOS) {
  103.         column++;
  104.  
  105.         if (*s == '\t') {
  106.             s++;
  107.             *(t + i) = ' ';
  108.             while (column % tabsize) {
  109.                 i++;
  110.                 *(t + i) = ' ';
  111.                 column++;
  112.             }
  113.         }
  114.         else
  115.             *(t + i) = *s++;
  116.  
  117.         /* if ((strlen(t) > rm) || (*(t + i) == '\n'))    */
  118.         /*    if (strlen(t) > rm)             */
  119.  
  120.         if ((i >= rm) || (*(t + i) == '\n')) {
  121.             if ((workcount++ & 31) == 0)
  122.               working(TRUE);
  123.  
  124.             column = 0;
  125.             if (i >= rm) {
  126.                                 memset(tmp, 0, (rm + rm/2));
  127.                 t1 = t + i;
  128.  
  129.                 while (!isspace(*t1) && (t1 > t))
  130.                     t1--;
  131.  
  132.                 if (t1 <= t) {
  133.                     t1 = t + i;
  134.                     while (!ispunct(*t1) && (t1 > t))
  135.                         t1--;
  136.                 }
  137.  
  138.                 if (t1 <= t)
  139.                                         t1 = t + i - 1;
  140.  
  141.                                 while (isspace(*t1))
  142.                                         t1++;
  143.  
  144.                                 strcpy(tmp, t1);
  145.                 *t1 = '\0';
  146.             }
  147.             else
  148.                                 memset(tmp, 0, (rm + rm/2));
  149.  
  150.             if ((p = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
  151.                 ptrfree(t);
  152.                 ptrfree(tmp);
  153.                 return buf;
  154.             }
  155.  
  156.                         if ((p->text = strdup(t)) == NULL) {
  157.                 ptrfree(p);
  158.                 ptrfree(t);
  159.                 ptrfree(tmp);
  160.                 return buf;
  161.             }
  162.  
  163.             if (*p->text == '\01')
  164.                 p->hide = 1;
  165.  
  166.             { register char *otmp = strchr(p->text,'>');
  167.             if ((otmp != NULL) && (otmp - p->text < GUTTER))
  168.                 p->quote = 1;
  169.             } /* island */
  170.  
  171.             if (buf.first == NULL) {
  172.                 buf.first = p;
  173.                 buf.last = p;
  174.                 p->next = NULL;
  175.                 p->prev = NULL;
  176.                                 memset(t, 0, (rm + rm/2));
  177.                 strcpy(t, tmp);
  178.                 i = strlen(t);
  179.                 continue;
  180.             }
  181.  
  182.             p->next = buf.last->next;
  183.             buf.last->next = p;
  184.             p->prev = buf.last;
  185.             buf.last = p;
  186.  
  187.                         memset(t, 0, (rm + rm/2));
  188.             strcpy(t, tmp);
  189.             i = strlen(t);
  190.         }
  191.         else
  192.             i++;
  193.     } /* while */
  194.     watch(3);
  195.  
  196.     if (strlen(t) > 0) {
  197.         if ((p = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
  198.             ptrfree(tmp);
  199.             ptrfree(t);
  200.             return buf;
  201.         }
  202.  
  203.         if ((p->text = strdup(t)) == NULL) {
  204.             ptrfree(p);
  205.             ptrfree(t);
  206.             ptrfree(tmp);
  207.             return buf;
  208.         }
  209.  
  210.         if (buf.first == NULL) {
  211.             buf.first = p;
  212.             buf.last = p;
  213.             p->next = NULL;
  214.             p->prev = NULL;
  215.         }
  216.         else {
  217.             p->next = buf.last ->next;
  218.             buf.last->next = p;
  219.             p->prev = buf.last;
  220.             buf.last = p;
  221.         }
  222.  
  223.         if (*p->text == '\01')
  224.             p->hide = 1;
  225.  
  226.         if (((strchr(p->text,'>') - p->text) < GUTTER) && (strchr(p->text,'>')))
  227.             p->quote = 1;
  228.     }
  229.     watch(-1);
  230.     ptrfree(tmp);
  231.         ptrfree(t);
  232.     if (buf.first != NULL)
  233.         buf.first->prev = NULL;
  234.     if (buf.last != NULL)
  235.         buf.last->next = NULL;
  236.     working(FALSE);
  237.  
  238.     return buf;
  239. } /* buffer */
  240.  
  241. static void normalize(char *s)
  242. {
  243.     char *tmp = s;
  244.     char *org = s;
  245.  
  246.     while (*s != EOS) {
  247.         switch (*s) {
  248.             case (char) 0x8d:
  249.             case (char) 0x0a:
  250.                 s++;
  251.                 continue;
  252.             case (char) 0x0d:
  253.                 s++;
  254.                 *tmp = '\n';
  255.                 break;
  256.             default:
  257.                 *tmp = *s++;
  258.                 break;
  259.         }
  260.         tmp++;
  261.     }
  262.     *tmp = EOS;
  263.  
  264.     if (rot13 != 0)
  265.       for (s = org;  *s != EOS;  s++)
  266.         *s = dorot13(*s);
  267. }
  268. #endif
  269.  
  270. /*
  271.  * Copy lookahead characters to line buffer
  272.  * s is start, scol is col at start
  273.  * p is end (inclusive)
  274.  * *d is destination and is updated and zero-terminated
  275.  * returns pointer p+1
  276.  */
  277.  
  278. static char *copychars(int *scol, char *s, char *p, char **d)
  279. {
  280.   int c;
  281.  
  282.   while (s <= p) {
  283.     switch (*s) {
  284.       case '\n':
  285.       case (char)0x8d:
  286.     ++s;
  287.     break;
  288.  
  289.       case '\t':
  290.     c = tabsize-(*scol % tabsize);    /* spaces to skip */
  291.     *scol += c;
  292.     while (c--)
  293.       *(*d)++ = ' ';
  294.     ++s;
  295.     break;
  296.  
  297.       case '\r':
  298.     *(*d)++ = '\n';  ++s;
  299.     ++(*scol);
  300.     break;
  301.  
  302.       default:
  303.     *(*d)++ = *s++;
  304.     ++(*scol);
  305.     break;
  306.     } /* switch */
  307.   }
  308.  
  309.   *(*d) = EOS;
  310.   return s;
  311. } /* copychars */
  312.  
  313. static BOOLEAN addline(BUFFER *buf, char *text)
  314. {
  315.   static int workcount = 0;        /* slow down working indicator */
  316.   LINE *p;
  317.   char *grin;
  318.  
  319.   if ((workcount++ & 31) == 0)
  320.     working(TRUE);
  321.  
  322.   if ((p = insertline(buf, NULL, text)) == NULL)
  323.     return FALSE;
  324.  
  325.   if (text[0] == '\01')
  326.     p->hide = 1;
  327.  
  328.   text = strchr(p->text, '>');
  329.   grin = strchr(p->text, '<');  /* don't quote "<grin>" at start */
  330.   if ((text != NULL) && (text - p->text < GUTTER) &&
  331.       ((grin == NULL) || (grin > text)))
  332.     p->quote = 1;
  333.  
  334.   return TRUE;
  335. } /* addline */
  336.  
  337. BUFFER buffer(char **ss)        /* NEW(est) version */
  338. {
  339.   register char *s, *p;
  340.   int scol, pcol;
  341.   char *d, *text;
  342.   BUFFER buf;
  343.  
  344.   buf.first = buf.last = NULL;
  345.   clearbuffer(&msgbuf);            /* clear global (yuck) buffer */
  346.  
  347.   text = (char *)malloc(rm + rm/2);    /* add some fudge for taste */
  348.   if (text == NULL) return buf;        /* sorry pal */
  349.  
  350.   if (rot13 != 0)            /* do rotation pass */
  351.     for (s = *ss;  *s != EOS;  s++)
  352.       *s = dorot13(*s);
  353.  
  354.   p = s = *ss;  pcol = scol = 0;    /* s is source, p is peek */
  355.   d = text;  *d = EOS;            /* d is dest */
  356.  
  357.   for (;;) {    /* loop over p by 1 (sometimes backtrack to checkpoint) */
  358.         /* pcol is col at p (increases or stays same) */
  359.         /* s is last checkpoint */
  360.         /* scol is col at s */
  361.         /* d is destination inside text */
  362.  
  363. /* if at end of buffer, finish current line and exit */
  364.  
  365.     if (*p == EOS) {            /* end of text */
  366.       if (p > s) {            /* we still have sometime left */
  367.     (void)copychars(&scol, s, p-1, &d);
  368.     (void)addline(&buf, text);
  369.       } /* if */
  370.       break;                /* end of buffer */
  371.  
  372. /* if at/past margin, start new line or smash current line (break badly) */
  373.  
  374.     } else if (pcol >= rm) {        /* at margin */
  375.       if (scol == 0) {            /* bad break! */
  376.     p = s = copychars(&scol, s, p, &d);
  377.     pcol = scol = 0;
  378.     if (!addline(&buf, text))
  379.       break;
  380.  
  381.       } else {                /* freeze line at last checkpoint */
  382.     if (!addline(&buf, text))
  383.       break;
  384.     p = s;  pcol = scol = 0;    /* start over at last checkpoint */
  385.  
  386.       } /* else */
  387.       d = text;  *d = EOS;
  388.  
  389.     } else if (*p == '\r') {        /* end of line */
  390.       p = s = copychars(&scol, s, p, &d);
  391.       pcol = scol = 0;
  392.       if (!addline(&buf, text))
  393.     break;
  394.       d = text;  *d = EOS;
  395.  
  396.                         /* can break line here */
  397.     } else if ((*p == ' ') || (*p == '\t') || (*p == '-')) {
  398.       p = s = copychars(&scol, s, p, &d);    /* 'checkpoint' */
  399.       pcol = scol;
  400.  
  401.     } else if ((*p == '\n') || (*p == (char)0x8d)) {    /* ignore */
  402.       ++p;
  403.  
  404.     } else {                /* all other characters */
  405.       ++pcol;
  406.       ++p;
  407.     } /* else */
  408.  
  409.   } /* endless */
  410.  
  411.   ptrfree(text);
  412.   working(FALSE);            /* remove indicator */
  413.  
  414.   return buf;
  415. } /* buffer */
  416.